#include "iuPacketICMP.hpp"
#include <arpa/inet.h>

/**
 * @brief Initialise le paquet ICMP
 */
iuPacketICMP::iuPacketICMP()
{
   m_type = ICMP_ECHO_REQUEST;
   m_size = 4;
}

/**
 * @brief Calcule la longueur du paquet ICMP. Lorsque fromBuffer() est appelee, le buffer
 * passe en parametre devra avoir au moins cette taille
 * @return Renvoie la longueur du paquet ICMP
 */
uint16_t iuPacketICMP::getBufferLen() const
{
   uint16_t len;
   
   //Somme de la taille des differents champs du paquet ICMP
   len = 1 + 1 + 2 + m_size;
   return len;
}

/**
 * @brief Lit le paquet ICMP a partir d'un buffer
 * @param buffer le buffer ou le paquet ICMP sera lu
 * @param len la longueur du paquet ICMP a lire
 * @return Renvoie le nombre d'octets lus
 * @note On suppose que le paquet est bien forme
 */
uint16_t iuPacketICMP::fromBuffer(const char *buffer, uint16_t len)
{
   const char *b = buffer;

   //Lit le type de la requete
   m_type = *b;
   b += 1;

   //Ignore le code et le checksum de la requete
   b += 3;

   //Calcule la taille des donnees
   m_size = len - (b - buffer);
   b += m_size;

   return (b - buffer);
}

/**
 * @brief Ecrit le paquet ICMP dans le buffer. Le buffer devra avoir une taille d'au
 * moins getBufferLen() octets
 * @param buffer l'adresse du debut du buffer dans lequel sera ecrit le paquet ICMP
 * @return Renvoie le nombre d'octets ecrits (== getBufferLen())
 */
uint16_t iuPacketICMP::toBuffer(char *buffer) const
{
   char *b = buffer;

   //Ecrit le type de la requete
   *b = m_type;
   b += 1;

   //Ecrit le code correspondant a la requete (ici 0)
   *b = 0;
   b += 1;

   //Ecrit le checksum valant 0
   WRITE16(b, 0);

   //Ignore les donnees
   b += m_size;

   return (b - buffer);
}

/**
 * @brief Attribue le type du paquet ICMP (ECHO_REQUEST ou ECHO_REPLY)
 * @param type le type a attribuer
 */
void iuPacketICMP::setType(uint8_t type)
{
   m_type = type;
}

/**
 * @brief Recupere le type du paquet ICMP (ECHO_REQUEST ou ECHO_REPLY)
 * @return Renvoie le type du paquet
 */
uint8_t iuPacketICMP::getType() const
{
   return m_type;
}

/**
 * @brief Attribue la taille des donnees
 * @param size la taille a attribuer
 */
void iuPacketICMP::setSize(uint16_t size)
{
   m_size = size;
}

/**
 * @brief Recupere la taille des donnees
 * @return Renvoie la taille
 */
uint16_t iuPacketICMP::getSize() const
{
   return m_size;
}
